(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jpeg = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  /*
   * Copyright (C) 2015 Michael Martinez
   * Changes: Added support for selection values 2-7, fixed minor bugs &
   * warnings, split into multiple class files, and general clean up.
   *
   * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT.
   */

  /*
   * Copyright (C) Helmut Dersch
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:

   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.

   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */

  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ***/
  var jpeg = jpeg || {};
  jpeg.lossless = jpeg.lossless || {};


  /*** Constructor ***/
  jpeg.lossless.ComponentSpec = jpeg.lossless.ComponentSpec || function () {
      this.hSamp = 0; // Horizontal sampling factor
      this.quantTableSel = 0; // Quantization table destination selector
      this.vSamp = 0; // Vertical
  };


  /*** Exports ***/

  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg.lossless.ComponentSpec;
  }

  },{}],2:[function(require,module,exports){
  /*
   * Copyright (C) 2015 Michael Martinez
   * Changes: Added support for selection values 2-7, fixed minor bugs &
   * warnings, split into multiple class files, and general clean up.
   *
   * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT.
   */

  /*
   * Copyright (C) Helmut Dersch
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:

   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.

   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */

  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ***/
  var jpeg = jpeg || {};
  jpeg.lossless = jpeg.lossless || {};


  /*** Constructor ***/
  jpeg.lossless.DataStream = jpeg.lossless.DataStream || function (data, offset, length) {
      // Note: DataView is much slower than Int8Array
      // this.buffer = new DataView(data, offset, length);
      this.buffer = new Uint8Array(data, offset, length);
      this.index = 0;
  };



  jpeg.lossless.DataStream.prototype.get16 = function () {
      // var value = this.buffer.getUint16(this.index, false);
      var value = (this.buffer[this.index] << 8) + this.buffer[this.index + 1]; // DataView is big-endian by default
      this.index += 2;
      return value;
  };



  jpeg.lossless.DataStream.prototype.get8 = function () {
      // var value = this.buffer.getUint8(this.index);
      var value = this.buffer[this.index];
      this.index += 1;
      return value;
  };


  /*** Exports ***/

  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg.lossless.DataStream;
  }

  },{}],3:[function(require,module,exports){
  /*
   * Copyright (C) 2015 Michael Martinez
   * Changes: Added support for selection values 2-7, fixed minor bugs &
   * warnings, split into multiple class files, and general clean up.
   *
   * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT.
   */

  /*
   * Copyright (C) Helmut Dersch
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:

   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.

   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */

  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ***/
  var jpeg = jpeg || {};
  jpeg.lossless = jpeg.lossless || {};
  jpeg.lossless.DataStream = jpeg.lossless.DataStream || ((typeof require !== 'undefined') ? require('./data-stream.js') : null);
  jpeg.lossless.HuffmanTable = jpeg.lossless.HuffmanTable || ((typeof require !== 'undefined') ? require('./huffman-table.js') : null);
  jpeg.lossless.QuantizationTable = jpeg.lossless.QuantizationTable || ((typeof require !== 'undefined') ? require('./quantization-table.js') : null);
  jpeg.lossless.ScanHeader = jpeg.lossless.ScanHeader || ((typeof require !== 'undefined') ? require('./scan-header.js') : null);
  jpeg.lossless.FrameHeader = jpeg.lossless.FrameHeader || ((typeof require !== 'undefined') ? require('./frame-header.js') : null);
  jpeg.lossless.Utils = jpeg.lossless.Utils || ((typeof require !== 'undefined') ? require('./utils.js') : null);


  /*** Constructor ***/

  /**
   * The Decoder constructor.
   * @property {number} xDim - size of x dimension
   * @property {number} yDim - size of y dimension
   * @property {number} numComp - number of components
   * @property {number} numBytes - number of bytes per component
   * @type {Function}
   */
  jpeg.lossless.Decoder = jpeg.lossless.Decoder || function (buffer, numBytes) {
      this.buffer = buffer;
      this.frame = new jpeg.lossless.FrameHeader();
      this.huffTable = new jpeg.lossless.HuffmanTable();
      this.quantTable = new jpeg.lossless.QuantizationTable();
      this.scan = new jpeg.lossless.ScanHeader();
      this.DU = jpeg.lossless.Utils.createArray(10, 4, 64); // at most 10 data units in a MCU, at most 4 data units in one component
      this.HuffTab = jpeg.lossless.Utils.createArray(4, 2, 50 * 256);
      this.IDCT_Source = [];
      this.nBlock = []; // number of blocks in the i-th Comp in a scan
      this.acTab = jpeg.lossless.Utils.createArray(10, 1); // ac HuffTab for the i-th Comp in a scan
      this.dcTab = jpeg.lossless.Utils.createArray(10, 1); // dc HuffTab for the i-th Comp in a scan
      this.qTab = jpeg.lossless.Utils.createArray(10, 1); // quantization table for the i-th Comp in a scan
      this.marker = 0;
      this.markerIndex = 0;
      this.numComp = 0;
      this.restartInterval = 0;
      this.selection = 0;
      this.xDim = 0;
      this.yDim = 0;
      this.xLoc = 0;
      this.yLoc = 0;
      this.numBytes = 0;
      this.outputData = null;
      this.restarting = false;
      this.mask = 0;

      if (typeof numBytes !== "undefined") {
          this.numBytes = numBytes;
      }
  };


  /*** Static Pseudo-constants ***/

  jpeg.lossless.Decoder.IDCT_P = [0, 5, 40, 16, 45, 2, 7, 42, 21, 56, 8, 61, 18, 47, 1, 4, 41, 23, 58, 13, 32, 24, 37, 10, 63, 17, 44, 3, 6, 43, 20,
      57, 15, 34, 29, 48, 53, 26, 39, 9, 60, 19, 46, 22, 59, 12, 33, 31, 50, 55, 25, 36, 11, 62, 14, 35, 28, 49, 52, 27, 38, 30, 51, 54];
  jpeg.lossless.Decoder.TABLE = [0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53,
      10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63];
  jpeg.lossless.Decoder.MAX_HUFFMAN_SUBTREE = 50;
  jpeg.lossless.Decoder.MSB = 0x80000000;
  jpeg.lossless.Decoder.RESTART_MARKER_BEGIN = 0xFFD0;
  jpeg.lossless.Decoder.RESTART_MARKER_END = 0xFFD7;

  /*** Prototype Methods ***/

  /**
   * Returns decompressed data.
   * @param {ArrayBuffer} buffer
   * @param {number} [offset]
   * @param {number} [length]
   * @returns {ArrayBufer}
   */
  jpeg.lossless.Decoder.prototype.decompress = function (buffer, offset, length) {
      return this.decode(buffer, offset, length).buffer;
  };



  jpeg.lossless.Decoder.prototype.decode = function (buffer, offset, length, numBytes) {
      /*jslint bitwise: true */

      var current, scanNum = 0, pred = [], i, compN, temp = [], index = [], mcuNum;

      if (typeof buffer !== "undefined") {
          this.buffer = buffer;
      }

      if (typeof numBytes !== "undefined") {
          this.numBytes = numBytes;
      }

      this.stream = new jpeg.lossless.DataStream(this.buffer, offset, length);
      this.buffer = null;

      this.xLoc = 0;
      this.yLoc = 0;
      current = this.stream.get16();

      if (current !== 0xFFD8) { // SOI
          throw new Error("Not a JPEG file");
      }

      current = this.stream.get16();

      while ((((current >> 4) !== 0x0FFC) || (current === 0xFFC4))) { // SOF 0~15
          switch (current) {
              case 0xFFC4: // DHT
                  this.huffTable.read(this.stream, this.HuffTab);
                  break;
              case 0xFFCC: // DAC
                  throw new Error("Program doesn't support arithmetic coding. (format throw new IOException)");
              case 0xFFDB:
                  this.quantTable.read(this.stream, jpeg.lossless.Decoder.TABLE);
                  break;
              case 0xFFDD:
                  this.restartInterval = this.readNumber();
                  break;
              case 0xFFE0:
              case 0xFFE1:
              case 0xFFE2:
              case 0xFFE3:
              case 0xFFE4:
              case 0xFFE5:
              case 0xFFE6:
              case 0xFFE7:
              case 0xFFE8:
              case 0xFFE9:
              case 0xFFEA:
              case 0xFFEB:
              case 0xFFEC:
              case 0xFFED:
              case 0xFFEE:
              case 0xFFEF:
                  this.readApp();
                  break;
              case 0xFFFE:
                  this.readComment();
                  break;
              default:
                  if ((current >> 8) !== 0xFF) {
                      throw new Error("ERROR: format throw new IOException! (decode)");
                  }
          }

          current = this.stream.get16();
      }

      if ((current < 0xFFC0) || (current > 0xFFC7)) {
          throw new Error("ERROR: could not handle arithmetic code!");
      }

      this.frame.read(this.stream);
      current = this.stream.get16();

      do {
          while (current !== 0x0FFDA) { // SOS
              switch (current) {
                  case 0xFFC4: // DHT
                      this.huffTable.read(this.stream, this.HuffTab);
                      break;
                  case 0xFFCC: // DAC
                      throw new Error("Program doesn't support arithmetic coding. (format throw new IOException)");
                  case 0xFFDB:
                      this.quantTable.read(this.stream, jpeg.lossless.Decoder.TABLE);
                      break;
                  case 0xFFDD:
                      this.restartInterval = this.readNumber();
                      break;
                  case 0xFFE0:
                  case 0xFFE1:
                  case 0xFFE2:
                  case 0xFFE3:
                  case 0xFFE4:
                  case 0xFFE5:
                  case 0xFFE6:
                  case 0xFFE7:
                  case 0xFFE8:
                  case 0xFFE9:
                  case 0xFFEA:
                  case 0xFFEB:
                  case 0xFFEC:
                  case 0xFFED:
                  case 0xFFEE:
                  case 0xFFEF:
                      this.readApp();
                      break;
                  case 0xFFFE:
                      this.readComment();
                      break;
                  default:
                      if ((current >> 8) !== 0xFF) {
                          throw new Error("ERROR: format throw new IOException! (Parser.decode)");
                      }
              }

              current = this.stream.get16();
          }

          this.precision = this.frame.precision;
          this.components = this.frame.components;

          if (!this.numBytes) {
              this.numBytes = parseInt(Math.ceil(this.precision / 8));
          }

          if (this.numBytes == 1) {
              this.mask = 0xFF;
          } else {
              this.mask = 0xFFFF;
          }

          this.scan.read(this.stream);
          this.numComp = this.scan.numComp;
          this.selection = this.scan.selection;

          if (this.numBytes === 1) {
              if (this.numComp === 3) {
                  this.getter = this.getValueRGB;
                  this.setter = this.setValueRGB;
                  this.output = this.outputRGB;
              } else {
                  this.getter = this.getValue8;
                  this.setter = this.setValue8;
                  this.output = this.outputSingle;
              }
          } else {
              this.getter = this.getValue16;
              this.setter = this.setValue16;
              this.output = this.outputSingle;
          }

          switch (this.selection) {
              case 2:
                  this.selector = this.select2;
                  break;
              case 3:
                  this.selector = this.select3;
                  break;
              case 4:
                  this.selector = this.select4;
                  break;
              case 5:
                  this.selector = this.select5;
                  break;
              case 6:
                  this.selector = this.select6;
                  break;
              case 7:
                  this.selector = this.select7;
                  break;
              default:
                  this.selector = this.select1;
                  break;
          }

          this.scanComps = this.scan.components;
          this.quantTables = this.quantTable.quantTables;

          for (i = 0; i < this.numComp; i+=1) {
              compN = this.scanComps[i].scanCompSel;
              this.qTab[i] = this.quantTables[this.components[compN].quantTableSel];
              this.nBlock[i] = this.components[compN].vSamp * this.components[compN].hSamp;
              this.dcTab[i] = this.HuffTab[this.scanComps[i].dcTabSel][0];
              this.acTab[i] = this.HuffTab[this.scanComps[i].acTabSel][1];
          }

          this.xDim = this.frame.dimX;
          this.yDim = this.frame.dimY;
          if (this.numBytes == 1) {
              this.outputData = new Uint8Array(new ArrayBuffer(this.xDim * this.yDim * this.numBytes * this.numComp));
          } else {
              this.outputData = new Uint16Array(new ArrayBuffer(this.xDim * this.yDim * this.numBytes * this.numComp));
          }

          scanNum+=1;

          while (true) { // Decode one scan
              temp[0] = 0;
              index[0] = 0;

              for (i = 0; i < 10; i+=1) {
                  pred[i] = (1 << (this.precision - 1));
              }

              if (this.restartInterval === 0) {
                  current = this.decodeUnit(pred, temp, index);

                  while ((current === 0) && ((this.xLoc < this.xDim) && (this.yLoc < this.yDim))) {
                      this.output(pred);
                      current = this.decodeUnit(pred, temp, index);
                  }

                  break; //current=MARKER
              }

              for (mcuNum = 0; mcuNum < this.restartInterval; mcuNum+=1) {
                  this.restarting = (mcuNum == 0);
                  current = this.decodeUnit(pred, temp, index);
                  this.output(pred);

                  if (current !== 0) {
                      break;
                  }
              }

              if (current === 0) {
                  if (this.markerIndex !== 0) {
                      current = (0xFF00 | this.marker);
                      this.markerIndex = 0;
                  } else {
                      current = this.stream.get16();
                  }
              }

              if (!((current >= jpeg.lossless.Decoder.RESTART_MARKER_BEGIN) &&
                  (current <= jpeg.lossless.Decoder.RESTART_MARKER_END))) {
                  break; //current=MARKER
              }
          }

          if ((current === 0xFFDC) && (scanNum === 1)) { //DNL
              this.readNumber();
              current = this.stream.get16();
          }
      } while ((current !== 0xFFD9) && ((this.xLoc < this.xDim) && (this.yLoc < this.yDim)) && (scanNum === 0));

      return this.outputData;
  };



  jpeg.lossless.Decoder.prototype.decodeUnit = function (prev, temp, index) {
      if (this.numComp == 1) {
          return this.decodeSingle(prev, temp, index);
      } else if (this.numComp == 3) {
          return this.decodeRGB(prev, temp, index);
      } else {
          return -1;
      }
  };



  jpeg.lossless.Decoder.prototype.select1 = function (compOffset) {
      return this.getPreviousX(compOffset);
  };



  jpeg.lossless.Decoder.prototype.select2 = function (compOffset) {
      return this.getPreviousY(compOffset);
  };



  jpeg.lossless.Decoder.prototype.select3 = function (compOffset) {
      return this.getPreviousXY(compOffset);
  };



  jpeg.lossless.Decoder.prototype.select4 = function (compOffset) {
      return (this.getPreviousX(compOffset) + this.getPreviousY(compOffset)) - this.getPreviousXY(compOffset);
  };



  jpeg.lossless.Decoder.prototype.select5 = function (compOffset) {
      return this.getPreviousX(compOffset) + ((this.getPreviousY(compOffset) - this.getPreviousXY(compOffset)) >> 1);
  };



  jpeg.lossless.Decoder.prototype.select6 = function (compOffset) {
      return this.getPreviousY(compOffset) + ((this.getPreviousX(compOffset) - this.getPreviousXY(compOffset)) >> 1);
  };



  jpeg.lossless.Decoder.prototype.select7 = function (compOffset) {
      return ((this.getPreviousX(compOffset) + this.getPreviousY(compOffset)) / 2);
  };



  jpeg.lossless.Decoder.prototype.decodeRGB = function (prev, temp, index) {
      /*jslint bitwise: true */

      var value, actab, dctab, qtab, ctrC, i, k, j;

      prev[0] = this.selector(0);
      prev[1] = this.selector(1);
      prev[2] = this.selector(2);

      for (ctrC = 0; ctrC < this.numComp; ctrC+=1) {
          qtab = this.qTab[ctrC];
          actab = this.acTab[ctrC];
          dctab = this.dcTab[ctrC];
          for (i = 0; i < this.nBlock[ctrC]; i+=1) {
              for (k = 0; k < this.IDCT_Source.length; k+=1) {
                  this.IDCT_Source[k] = 0;
              }

              value = this.getHuffmanValue(dctab, temp, index);

              if (value >= 0xFF00) {
                  return value;
              }

              prev[ctrC] = this.IDCT_Source[0] = prev[ctrC] + this.getn(index, value, temp, index);
              this.IDCT_Source[0] *= qtab[0];

              for (j = 1; j < 64; j+=1) {
                  value = this.getHuffmanValue(actab, temp, index);

                  if (value >= 0xFF00) {
                      return value;
                  }

                  j += (value >> 4);

                  if ((value & 0x0F) === 0) {
                      if ((value >> 4) === 0) {
                          break;
                      }
                  } else {
                      this.IDCT_Source[jpeg.lossless.Decoder.IDCT_P[j]] = this.getn(index, value & 0x0F, temp, index) * qtab[j];
                  }
              }
          }
      }

      return 0;
  };



  jpeg.lossless.Decoder.prototype.decodeSingle = function (prev, temp, index) {
      /*jslint bitwise: true */

      var value, i, n, nRestart;

      if (this.restarting) {
          this.restarting = false;
          prev[0] = (1 << (this.frame.precision - 1));
      } else {
          prev[0] = this.selector();
      }

      for (i = 0; i < this.nBlock[0]; i+=1) {
          value = this.getHuffmanValue(this.dcTab[0], temp, index);
          if (value >= 0xFF00) {
              return value;
          }

          n = this.getn(prev, value, temp, index);
          nRestart = (n >> 8);

          if ((nRestart >= jpeg.lossless.Decoder.RESTART_MARKER_BEGIN) && (nRestart <= jpeg.lossless.Decoder.RESTART_MARKER_END)) {
              return nRestart;
          }

          prev[0] += n;
      }

      return 0;
  };



  //  Huffman table for fast search: (HuffTab) 8-bit Look up table 2-layer search architecture, 1st-layer represent 256 node (8 bits) if codeword-length > 8
  //  bits, then the entry of 1st-layer = (# of 2nd-layer table) | MSB and it is stored in the 2nd-layer Size of tables in each layer are 256.
  //  HuffTab[*][*][0-256] is always the only 1st-layer table.
  //
  //  An entry can be: (1) (# of 2nd-layer table) | MSB , for code length > 8 in 1st-layer (2) (Code length) << 8 | HuffVal
  //
  //  HuffmanValue(table   HuffTab[x][y] (ex) HuffmanValue(HuffTab[1][0],...)
  //                  ):
  //      return: Huffman Value of table
  //              0xFF?? if it receives a MARKER
  //      Parameter:  table   HuffTab[x][y] (ex) HuffmanValue(HuffTab[1][0],...)
  //                  temp    temp storage for remainded bits
  //                  index   index to bit of temp
  //                  in      FILE pointer
  //      Effect:
  //          temp  store new remainded bits
  //          index change to new index
  //          in    change to new position
  //      NOTE:
  //        Initial by   temp=0; index=0;
  //      NOTE: (explain temp and index)
  //        temp: is always in the form at calling time or returning time
  //         |  byte 4  |  byte 3  |  byte 2  |  byte 1  |
  //         |     0    |     0    | 00000000 | 00000??? |  if not a MARKER
  //                                                 ^index=3 (from 0 to 15)
  //                                                 321
  //      NOTE (marker and marker_index):
  //        If get a MARKER from 'in', marker=the low-byte of the MARKER
  //          and marker_index=9
  //        If marker_index=9 then index is always > 8, or HuffmanValue()
  //          will not be called
  jpeg.lossless.Decoder.prototype.getHuffmanValue = function (table, temp, index) {
      /*jslint bitwise: true */

      var code, input, mask;
      mask = 0xFFFF;

      if (index[0] < 8) {
          temp[0] <<= 8;
          input = this.stream.get8();
          if (input === 0xFF) {
              this.marker = this.stream.get8();
              if (this.marker !== 0) {
                  this.markerIndex = 9;
              }
          }
          temp[0] |= input;
      } else {
          index[0] -= 8;
      }

      code = table[temp[0] >> index[0]];

      if ((code & jpeg.lossless.Decoder.MSB) !== 0) {
          if (this.markerIndex !== 0) {
              this.markerIndex = 0;
              return 0xFF00 | this.marker;
          }

          temp[0] &= (mask >> (16 - index[0]));
          temp[0] <<= 8;
          input = this.stream.get8();

          if (input === 0xFF) {
              this.marker = this.stream.get8();
              if (this.marker !== 0) {
                  this.markerIndex = 9;
              }
          }

          temp[0] |= input;
          code = table[((code & 0xFF) * 256) + (temp[0] >> index[0])];
          index[0] += 8;
      }

      index[0] += 8 - (code >> 8);

      if (index[0] < 0) {
          throw new Error("index=" + index[0] + " temp=" + temp[0] + " code=" + code + " in HuffmanValue()");
      }

      if (index[0] < this.markerIndex) {
          this.markerIndex = 0;
          return 0xFF00 | this.marker;
      }

      temp[0] &= (mask >> (16 - index[0]));
      return code & 0xFF;
  };



  jpeg.lossless.Decoder.prototype.getn = function (PRED, n, temp, index) {
      /*jslint bitwise: true */

      var result, one, n_one, mask, input;
      one = 1;
      n_one = -1;
      mask = 0xFFFF;

      if (n === 0) {
          return 0;
      }

      if (n === 16) {
          if (PRED[0] >= 0) {
              return -32768;
          } else {
              return 32768;
          }
      }

      index[0] -= n;

      if (index[0] >= 0) {
          if ((index[0] < this.markerIndex) && !this.isLastPixel()) { // this was corrupting the last pixel in some cases
              this.markerIndex = 0;
              return (0xFF00 | this.marker) << 8;
          }

          result = temp[0] >> index[0];
          temp[0] &= (mask >> (16 - index[0]));
      } else {
          temp[0] <<= 8;
          input = this.stream.get8();

          if (input === 0xFF) {
              this.marker = this.stream.get8();
              if (this.marker !== 0) {
                  this.markerIndex = 9;
              }
          }

          temp[0] |= input;
          index[0] += 8;

          if (index[0] < 0) {
              if (this.markerIndex !== 0) {
                  this.markerIndex = 0;
                  return (0xFF00 | this.marker) << 8;
              }

              temp[0] <<= 8;
              input = this.stream.get8();

              if (input === 0xFF) {
                  this.marker = this.stream.get8();
                  if (this.marker !== 0) {
                      this.markerIndex = 9;
                  }
              }

              temp[0] |= input;
              index[0] += 8;
          }

          if (index[0] < 0) {
              throw new Error("index=" + index[0] + " in getn()");
          }

          if (index[0] < this.markerIndex) {
              this.markerIndex = 0;
              return (0xFF00 | this.marker) << 8;
          }

          result = temp[0] >> index[0];
          temp[0] &= (mask >> (16 - index[0]));
      }

      if (result < (one << (n - 1))) {
          result += (n_one << n) + 1;
      }

      return result;
  };



  jpeg.lossless.Decoder.prototype.getPreviousX = function (compOffset) {
      /*jslint bitwise: true */

      if (this.xLoc > 0) {
          return this.getter((((this.yLoc * this.xDim) + this.xLoc) - 1), compOffset);
      } else if (this.yLoc > 0) {
          return this.getPreviousY(compOffset);
      } else {
          return (1 << (this.frame.precision - 1));
      }
  };



  jpeg.lossless.Decoder.prototype.getPreviousXY = function (compOffset) {
      /*jslint bitwise: true */

      if ((this.xLoc > 0) && (this.yLoc > 0)) {
          return this.getter(((((this.yLoc - 1) * this.xDim) + this.xLoc) - 1), compOffset);
      } else {
          return this.getPreviousY(compOffset);
      }
  };



  jpeg.lossless.Decoder.prototype.getPreviousY = function (compOffset) {
      /*jslint bitwise: true */

      if (this.yLoc > 0) {
          return this.getter((((this.yLoc - 1) * this.xDim) + this.xLoc), compOffset);
      } else {
          return this.getPreviousX(compOffset);
      }
  };



  jpeg.lossless.Decoder.prototype.isLastPixel = function () {
      return (this.xLoc === (this.xDim - 1)) && (this.yLoc === (this.yDim - 1));
  };



  jpeg.lossless.Decoder.prototype.outputSingle = function (PRED) {
      if ((this.xLoc < this.xDim) && (this.yLoc < this.yDim)) {
          this.setter((((this.yLoc * this.xDim) + this.xLoc)), this.mask & PRED[0]);

          this.xLoc+=1;

          if (this.xLoc >= this.xDim) {
              this.yLoc+=1;
              this.xLoc = 0;
          }
      }
  };



  jpeg.lossless.Decoder.prototype.outputRGB = function (PRED) {
      var offset = ((this.yLoc * this.xDim) + this.xLoc);

      if ((this.xLoc < this.xDim) && (this.yLoc < this.yDim)) {
          this.setter(offset, PRED[0], 0);
          this.setter(offset, PRED[1], 1);
          this.setter(offset, PRED[2], 2);

          this.xLoc+=1;

          if (this.xLoc >= this.xDim) {
              this.yLoc+=1;
              this.xLoc = 0;
          }
      }
  };

  jpeg.lossless.Decoder.prototype.setValue8 = function (index, val) {
      this.outputData[index] = val; 
  };

  jpeg.lossless.Decoder.prototype.getValue8 = function (index) {
      return this.outputData[index]; // mask should not be necessary because outputData is either Int8Array or Int16Array
  };

  var littleEndian = (function() {
      var buffer = new ArrayBuffer(2);
      new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
      // Int16Array uses the platform's endianness.
      return new Int16Array(buffer)[0] === 256;
  })();

  if (littleEndian) {
      // just reading from an array is fine then. Int16Array will use platform endianness.
      jpeg.lossless.Decoder.prototype.setValue16 = jpeg.lossless.Decoder.prototype.setValue8; 
      jpeg.lossless.Decoder.prototype.getValue16 = jpeg.lossless.Decoder.prototype.getValue8;
  } 
  else {
      // If platform is big-endian, we will need to convert to little-endian 
      jpeg.lossless.Decoder.prototype.setValue16 = function (index, val) {
          this.outputData[index] = ((val & 0xFF) << 8) | ((val >> 8) & 0xFF); 
      };

      jpeg.lossless.Decoder.prototype.getValue16 = function (index) {
          var val = this.outputData[index];
          return ((val & 0xFF) << 8) | ((val >> 8) & 0xFF);
      };
  }

  jpeg.lossless.Decoder.prototype.setValueRGB = function (index, val, compOffset) {
      // this.outputData.setUint8(index * 3 + compOffset, val);
      this.outputData[index * 3 + compOffset] = val;
  };

  jpeg.lossless.Decoder.prototype.getValueRGB = function (index, compOffset) {
      // return this.outputData.getUint8(index * 3 + compOffset);
      return this.outputData[index * 3 + compOffset];
  };



  jpeg.lossless.Decoder.prototype.readApp = function() {
      var count = 0, length = this.stream.get16();
      count += 2;

      while (count < length) {
          this.stream.get8();
          count+=1;
      }

      return length;
  };



  jpeg.lossless.Decoder.prototype.readComment = function () {
      var sb = "", count = 0, length;

      length = this.stream.get16();
      count += 2;

      while (count < length) {
          sb += this.stream.get8();
          count+=1;
      }

      return sb;
  };



  jpeg.lossless.Decoder.prototype.readNumber = function() {
      var Ld = this.stream.get16();

      if (Ld !== 4) {
          throw new Error("ERROR: Define number format throw new IOException [Ld!=4]");
      }

      return this.stream.get16();
  };



  /*** Exports ***/

  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg.lossless.Decoder;
  }

  },{"./data-stream.js":2,"./frame-header.js":4,"./huffman-table.js":5,"./quantization-table.js":7,"./scan-header.js":9,"./utils.js":10}],4:[function(require,module,exports){
  /*
   * Copyright (C) 2015 Michael Martinez
   * Changes: Added support for selection values 2-7, fixed minor bugs &
   * warnings, split into multiple class files, and general clean up.
   *
   * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT.
   */

  /*
   * Copyright (C) Helmut Dersch
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:

   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.

   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */

  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ***/
  var jpeg = jpeg || {};
  jpeg.lossless = jpeg.lossless || {};
  jpeg.lossless.ComponentSpec = jpeg.lossless.ComponentSpec || ((typeof require !== 'undefined') ? require('./component-spec.js') : null);
  jpeg.lossless.DataStream = jpeg.lossless.DataStream || ((typeof require !== 'undefined') ? require('./data-stream.js') : null);


  /*** Constructor ***/
  jpeg.lossless.FrameHeader = jpeg.lossless.FrameHeader || function () {
      this.components = []; // Components
      this.dimX = 0; // Number of samples per line
      this.dimY = 0; // Number of lines
      this.numComp = 0; // Number of component in the frame
      this.precision = 0; // Sample Precision (from the original image)
  };



  /*** Prototype Methods ***/

  jpeg.lossless.FrameHeader.prototype.read = function (data) {
      /*jslint bitwise: true */

      var count = 0, length, i, c, temp;

      length = data.get16();
      count += 2;

      this.precision = data.get8();
      count+=1;

      this.dimY = data.get16();
      count += 2;

      this.dimX = data.get16();
      count += 2;

      this.numComp = data.get8();
      count+=1;
      for (i = 1; i <= this.numComp; i+=1) {
          if (count > length) {
              throw new Error("ERROR: frame format error");
          }

          c = data.get8();
          count+=1;

          if (count >= length) {
              throw new Error("ERROR: frame format error [c>=Lf]");
          }

          temp = data.get8();
          count+=1;

          if (!this.components[c]) {
              this.components[c] = new jpeg.lossless.ComponentSpec();
          }

          this.components[c].hSamp = temp >> 4;
          this.components[c].vSamp = temp & 0x0F;
          this.components[c].quantTableSel = data.get8();
          count+=1;
      }

      if (count !== length) {
          throw new Error("ERROR: frame format error [Lf!=count]");
      }

      return 1;
  };


  /*** Exports ***/

  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg.lossless.FrameHeader;
  }

  },{"./component-spec.js":1,"./data-stream.js":2}],5:[function(require,module,exports){
  /*
   * Copyright (C) 2015 Michael Martinez
   * Changes: Added support for selection values 2-7, fixed minor bugs &
   * warnings, split into multiple class files, and general clean up.
   *
   * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT.
   */

  /*
   * Copyright (C) Helmut Dersch
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:

   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.

   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */

  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ***/
  var jpeg = jpeg || {};
  jpeg.lossless = jpeg.lossless || {};
  jpeg.lossless.DataStream = jpeg.lossless.DataStream || ((typeof require !== 'undefined') ? require('./data-stream.js') : null);
  jpeg.lossless.Utils = jpeg.lossless.Utils || ((typeof require !== 'undefined') ? require('./utils.js') : null);


  /*** Constructor ***/
  jpeg.lossless.HuffmanTable = jpeg.lossless.HuffmanTable || function () {
      this.l = jpeg.lossless.Utils.createArray(4, 2, 16);
      this.th = [];
      this.v = jpeg.lossless.Utils.createArray(4, 2, 16, 200);
      this.tc = jpeg.lossless.Utils.createArray(4, 2);

      this.tc[0][0] = 0;
      this.tc[1][0] = 0;
      this.tc[2][0] = 0;
      this.tc[3][0] = 0;
      this.tc[0][1] = 0;
      this.tc[1][1] = 0;
      this.tc[2][1] = 0;
      this.tc[3][1] = 0;
      this.th[0] = 0;
      this.th[1] = 0;
      this.th[2] = 0;
      this.th[3] = 0;
  };



  /*** Static Pseudo-constants ***/

  jpeg.lossless.HuffmanTable.MSB = 0x80000000;


  /*** Prototype Methods ***/

  jpeg.lossless.HuffmanTable.prototype.read = function(data, HuffTab) {
      /*jslint bitwise: true */

      var count = 0, length, temp, t, c, i, j;

      length = data.get16();
      count += 2;

      while (count < length) {
          temp = data.get8();
          count+=1;
          t = temp & 0x0F;
          if (t > 3) {
              throw new Error("ERROR: Huffman table ID > 3");
          }

          c = temp >> 4;
          if (c > 2) {
              throw new Error("ERROR: Huffman table [Table class > 2 ]");
          }

          this.th[t] = 1;
          this.tc[t][c] = 1;

          for (i = 0; i < 16; i+=1) {
              this.l[t][c][i] = data.get8();
              count+=1;
          }

          for (i = 0; i < 16; i+=1) {
              for (j = 0; j < this.l[t][c][i]; j+=1) {
                  if (count > length) {
                      throw new Error("ERROR: Huffman table format error [count>Lh]");
                  }

                  this.v[t][c][i][j] = data.get8();
                  count+=1;
              }
          }
      }

      if (count !== length) {
          throw new Error("ERROR: Huffman table format error [count!=Lf]");
      }

      for (i = 0; i < 4; i+=1) {
          for (j = 0; j < 2; j+=1) {
              if (this.tc[i][j] !== 0) {
                  this.buildHuffTable(HuffTab[i][j], this.l[i][j], this.v[i][j]);
              }
          }
      }

      return 1;
  };



  //  Build_HuffTab()
  //  Parameter:  t       table ID
  //              c       table class ( 0 for DC, 1 for AC )
  //              L[i]    # of codewords which length is i
  //              V[i][j] Huffman Value (length=i)
  //  Effect:
  //      build up HuffTab[t][c] using L and V.
  jpeg.lossless.HuffmanTable.prototype.buildHuffTable = function(tab, L, V) {
      /*jslint bitwise: true */

      var currentTable, temp, k, i, j, n;
      temp = 256;
      k = 0;

      for (i = 0; i < 8; i+=1) { // i+1 is Code length
          for (j = 0; j < L[i]; j+=1) {
              for (n = 0; n < (temp >> (i + 1)); n+=1) {
                  tab[k] = V[i][j] | ((i + 1) << 8);
                  k+=1;
              }
          }
      }

      for (i = 1; k < 256; i+=1, k+=1) {
          tab[k] = i | jpeg.lossless.HuffmanTable.MSB;
      }

      currentTable = 1;
      k = 0;

      for (i = 8; i < 16; i+=1) { // i+1 is Code length
          for (j = 0; j < L[i]; j+=1) {
              for (n = 0; n < (temp >> (i - 7)); n+=1) {
                  tab[(currentTable * 256) + k] = V[i][j] | ((i + 1) << 8);
                  k+=1;
              }

              if (k >= 256) {
                  if (k > 256) {
                      throw new Error("ERROR: Huffman table error(1)!");
                  }

                  k = 0;
                  currentTable+=1;
              }
          }
      }
  };


  /*** Exports ***/

  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg.lossless.HuffmanTable;
  }

  },{"./data-stream.js":2,"./utils.js":10}],6:[function(require,module,exports){
  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ****/

  /**
   * jpeg
    * @type {*|{}}
   */
  var jpeg = jpeg || {};

  /**
   * jpeg.lossless
   * @type {*|{}}
   */
  jpeg.lossless = jpeg.lossless || {};


  jpeg.lossless.ComponentSpec = jpeg.lossless.ComponentSpec || ((typeof require !== 'undefined') ? require('./component-spec.js') : null);
  jpeg.lossless.DataStream = jpeg.lossless.DataStream || ((typeof require !== 'undefined') ? require('./data-stream.js') : null);
  jpeg.lossless.Decoder = jpeg.lossless.Decoder || ((typeof require !== 'undefined') ? require('./decoder.js') : null);
  jpeg.lossless.FrameHeader = jpeg.lossless.FrameHeader || ((typeof require !== 'undefined') ? require('./frame-header.js') : null);
  jpeg.lossless.HuffmanTable = jpeg.lossless.HuffmanTable || ((typeof require !== 'undefined') ? require('./huffman-table.js') : null);
  jpeg.lossless.QuantizationTable = jpeg.lossless.QuantizationTable || ((typeof require !== 'undefined') ? require('./quantization-table.js') : null);
  jpeg.lossless.ScanComponent = jpeg.lossless.ScanComponent || ((typeof require !== 'undefined') ? require('./scan-component.js') : null);
  jpeg.lossless.ScanHeader = jpeg.lossless.ScanHeader || ((typeof require !== 'undefined') ? require('./scan-header.js') : null);
  jpeg.lossless.Utils = jpeg.lossless.Utils || ((typeof require !== 'undefined') ? require('./utils.js') : null);


  /*** Exports ***/
  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg;
  }

  },{"./component-spec.js":1,"./data-stream.js":2,"./decoder.js":3,"./frame-header.js":4,"./huffman-table.js":5,"./quantization-table.js":7,"./scan-component.js":8,"./scan-header.js":9,"./utils.js":10}],7:[function(require,module,exports){
  /*
   * Copyright (C) 2015 Michael Martinez
   * Changes: Added support for selection values 2-7, fixed minor bugs &
   * warnings, split into multiple class files, and general clean up.
   *
   * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT.
   */

  /*
   * Copyright (C) Helmut Dersch
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:

   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.

   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */

  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ***/
  var jpeg = jpeg || {};
  jpeg.lossless = jpeg.lossless || {};
  jpeg.lossless.DataStream = jpeg.lossless.DataStream || ((typeof require !== 'undefined') ? require('./data-stream.js') : null);
  jpeg.lossless.Utils = jpeg.lossless.Utils || ((typeof require !== 'undefined') ? require('./utils.js') : null);


  /*** Constructor ***/
  jpeg.lossless.QuantizationTable = jpeg.lossless.QuantizationTable || function () {
      this.precision = []; // Quantization precision 8 or 16
      this.tq = []; // 1: this table is presented
      this.quantTables = jpeg.lossless.Utils.createArray(4, 64); // Tables

      this.tq[0] = 0;
      this.tq[1] = 0;
      this.tq[2] = 0;
      this.tq[3] = 0;
  };



  /*** Static Methods ***/

  jpeg.lossless.QuantizationTable.enhanceQuantizationTable = function(qtab, table) {
      /*jslint bitwise: true */

      var i;

      for (i = 0; i < 8; i+=1) {
          qtab[table[(0 * 8) + i]] *= 90;
          qtab[table[(4 * 8) + i]] *= 90;
          qtab[table[(2 * 8) + i]] *= 118;
          qtab[table[(6 * 8) + i]] *= 49;
          qtab[table[(5 * 8) + i]] *= 71;
          qtab[table[(1 * 8) + i]] *= 126;
          qtab[table[(7 * 8) + i]] *= 25;
          qtab[table[(3 * 8) + i]] *= 106;
      }

      for (i = 0; i < 8; i+=1) {
          qtab[table[0 + (8 * i)]] *= 90;
          qtab[table[4 + (8 * i)]] *= 90;
          qtab[table[2 + (8 * i)]] *= 118;
          qtab[table[6 + (8 * i)]] *= 49;
          qtab[table[5 + (8 * i)]] *= 71;
          qtab[table[1 + (8 * i)]] *= 126;
          qtab[table[7 + (8 * i)]] *= 25;
          qtab[table[3 + (8 * i)]] *= 106;
      }

      for (i = 0; i < 64; i+=1) {
          qtab[i] >>= 6;
      }
  };


  /*** Prototype Methods ***/

  jpeg.lossless.QuantizationTable.prototype.read = function (data, table) {
      /*jslint bitwise: true */

      var count = 0, length, temp, t, i;

      length = data.get16();
      count += 2;

      while (count < length) {
          temp = data.get8();
          count+=1;
          t = temp & 0x0F;

          if (t > 3) {
              throw new Error("ERROR: Quantization table ID > 3");
          }

          this.precision[t] = temp >> 4;

          if (this.precision[t] === 0) {
              this.precision[t] = 8;
          } else if (this.precision[t] === 1) {
              this.precision[t] = 16;
          } else {
              throw new Error("ERROR: Quantization table precision error");
          }

          this.tq[t] = 1;

          if (this.precision[t] === 8) {
              for (i = 0; i < 64; i+=1) {
                  if (count > length) {
                      throw new Error("ERROR: Quantization table format error");
                  }

                  this.quantTables[t][i] = data.get8();
                  count+=1;
              }

              jpeg.lossless.QuantizationTable.enhanceQuantizationTable(this.quantTables[t], table);
          } else {
              for (i = 0; i < 64; i+=1) {
                  if (count > length) {
                      throw new Error("ERROR: Quantization table format error");
                  }

                  this.quantTables[t][i] = data.get16();
                  count += 2;
              }

              jpeg.lossless.QuantizationTable.enhanceQuantizationTable(this.quantTables[t], table);
          }
      }

      if (count !== length) {
          throw new Error("ERROR: Quantization table error [count!=Lq]");
      }

      return 1;
  };



  /*** Exports ***/

  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg.lossless.QuantizationTable;
  }

  },{"./data-stream.js":2,"./utils.js":10}],8:[function(require,module,exports){
  /*
   * Copyright (C) 2015 Michael Martinez
   * Changes: Added support for selection values 2-7, fixed minor bugs &
   * warnings, split into multiple class files, and general clean up.
   *
   * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT.
   */

  /*
   * Copyright (C) Helmut Dersch
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:

   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.

   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */

  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ***/
  var jpeg = jpeg || {};
  jpeg.lossless = jpeg.lossless || {};


  /*** Constructor ***/
  jpeg.lossless.ScanComponent = jpeg.lossless.ScanComponent || function () {
      this.acTabSel = 0; // AC table selector
      this.dcTabSel = 0; // DC table selector
      this.scanCompSel = 0; // Scan component selector
  };



  /*** Exports ***/

  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg.lossless.ScanComponent;
  }

  },{}],9:[function(require,module,exports){
  /*
   * Copyright (C) 2015 Michael Martinez
   * Changes: Added support for selection values 2-7, fixed minor bugs &
   * warnings, split into multiple class files, and general clean up.
   *
   * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT.
   */

  /*
   * Copyright (C) Helmut Dersch
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:

   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.

   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */

  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ***/
  var jpeg = jpeg || {};
  jpeg.lossless = jpeg.lossless || {};
  jpeg.lossless.DataStream = jpeg.lossless.DataStream || ((typeof require !== 'undefined') ? require('./data-stream.js') : null);
  jpeg.lossless.ScanComponent = jpeg.lossless.ScanComponent || ((typeof require !== 'undefined') ? require('./scan-component.js') : null);


  /*** Constructor ***/
  jpeg.lossless.ScanHeader = jpeg.lossless.ScanHeader || function () {
      this.ah = 0;
      this.al = 0;
      this.numComp = 0; // Number of components in the scan
      this.selection = 0; // Start of spectral or predictor selection
      this.spectralEnd = 0; // End of spectral selection
      this.components = [];
  };


  /*** Prototype Methods ***/

  jpeg.lossless.ScanHeader.prototype.read = function(data) {
      /*jslint bitwise: true */

      var count = 0, length, i, temp;

      length = data.get16();
      count += 2;

      this.numComp = data.get8();
      count+=1;

      for (i = 0; i < this.numComp; i+=1) {
          this.components[i] = new jpeg.lossless.ScanComponent();

          if (count > length) {
              throw new Error("ERROR: scan header format error");
          }

          this.components[i].scanCompSel = data.get8();
          count+=1;

          temp = data.get8();
          count+=1;

          this.components[i].dcTabSel = (temp >> 4);
          this.components[i].acTabSel = (temp & 0x0F);
      }

      this.selection = data.get8();
      count+=1;

      this.spectralEnd = data.get8();
      count+=1;

      temp = data.get8();
      this.ah = (temp >> 4);
      this.al = (temp & 0x0F);
      count+=1;

      if (count !== length) {
          throw new Error("ERROR: scan header format error [count!=Ns]");
      }

      return 1;
  };



  /*** Exports ***/

  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg.lossless.ScanHeader;
  }

  },{"./data-stream.js":2,"./scan-component.js":8}],10:[function(require,module,exports){
  /*
   * Copyright (C) 2015 Michael Martinez
   * Changes: Added support for selection values 2-7, fixed minor bugs &
   * warnings, split into multiple class files, and general clean up.
   *
   * 08-25-2015: Helmut Dersch agreed to a license change from LGPL to MIT.
   */

  /*
   * Copyright (C) Helmut Dersch
   *
   * Permission is hereby granted, free of charge, to any person obtaining a copy
   * of this software and associated documentation files (the "Software"), to deal
   * in the Software without restriction, including without limitation the rights
   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   * copies of the Software, and to permit persons to whom the Software is
   * furnished to do so, subject to the following conditions:

   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.

   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   */

  /*jslint browser: true, node: true */
  /*global require, module */

  "use strict";

  /*** Imports ***/
  var jpeg = jpeg || {};
  jpeg.lossless = jpeg.lossless || {};


  /*** Constructor ***/
  jpeg.lossless.Utils = jpeg.lossless.Utils || {};


  /*** Static methods ***/

  // http://stackoverflow.com/questions/966225/how-can-i-create-a-two-dimensional-array-in-javascript
  jpeg.lossless.Utils.createArray = function (length) {
      var arr = new Array(length || 0),
          i = length;

      if (arguments.length > 1) {
          var args = Array.prototype.slice.call(arguments, 1);
          while(i--) arr[length-1 - i] = jpeg.lossless.Utils.createArray.apply(this, args);
      }

      return arr;
  };


  // http://stackoverflow.com/questions/18638900/javascript-crc32
  jpeg.lossless.Utils.makeCRCTable = function(){
      var c;
      var crcTable = [];
      for(var n =0; n < 256; n++){
          c = n;
          for(var k =0; k < 8; k++){
              c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
          }
          crcTable[n] = c;
      }
      return crcTable;
  };

  jpeg.lossless.Utils.crc32 = function(dataView) {
      var uint8view = new Uint8Array(dataView.buffer);
      var crcTable = jpeg.lossless.Utils.crcTable || (jpeg.lossless.Utils.crcTable = jpeg.lossless.Utils.makeCRCTable());
      var crc = 0 ^ (-1);

      for (var i = 0; i < uint8view.length; i++ ) {
          crc = (crc >>> 8) ^ crcTable[(crc ^ uint8view[i]) & 0xFF];
      }

      return (crc ^ (-1)) >>> 0;
  };


  /*** Exports ***/

  var moduleType = typeof module;
  if ((moduleType !== 'undefined') && module.exports) {
      module.exports = jpeg.lossless.Utils;
  }

},{}]},{},[6])(6)
});